package ca.polymtl.rubikcube.util;

public final class Vect3f {
	/**
	 * The components of the vector.
	 */
	public final double x, y, z;
	
	/**
	 * Creates a vector with components (x,y,z)
	 * @param x
	 * @param y
	 * @param z
	 */
	public Vect3f(double x, double y, double z) {
		this.x = x;
		this.y = y;
		this.z = z;
	}

	/**
	 * Computes the square of the norm of the vector.
	 * @return
	 */
	public double norm2() {
		return x * x + y * y + z * z;
	}
	
	/**
	 * Computes the norm of the vector.
	 * @return The norm of the vector.
	 */
	public double norm() {
		return Math.sqrt(norm2());
	}
	
	/**
	 * Normalizes the vector.
	 * @return A normalized copy of the vector.
	 */
	public Vect3f normalized() {
		double n = norm();
		return new Vect3f(this.x / n, this.y / n, this.z / n);
	}
	
	/**
	 * Scales the vector.
	 * @param factor The scaling factor.
	 */
	public Vect3f scale(double factor) {
		return new Vect3f(this.x * factor, this.y * factor, this.z * factor);
	}
	
	public Vect3f divide(double factor) {
		return new Vect3f(this.x / factor, this.y / factor, this.z / factor);
	}
	
	/**
	 * Computes the sum of this vector and another.
	 * @param other
	 * @return The sum of this vector and another.
	 */
	public Vect3f add(Vect3f other) {
		return new Vect3f(this.x + other.x, this.y + other.y, this.z + other.z);
	}
	
	/**
	 * Computes the difference between this vector and another.
	 * @param other
	 * @return The sum of this vector and other.
	 */
	public Vect3f subtract(Vect3f other) {
		return new Vect3f(this.x - other.x, this.y - other.y, this.z - other.z);
	}
	
	/**
	 * Computes the dot product of this vector and rv.
	 * @param rv
	 * @return The dot product of this vector and rv.
	 */
	public double dot(Vect3f rv) {
		return x * rv.x + y * rv.y + z * rv.z;
	}
	
	/**
	 * Computes the cross product of this vector and rv.
	 * @param rv
	 * @return The cross product of this vector and rv.
	 */
	public Vect3f cross(Vect3f rv) {
		return new Vect3f(
				y * rv.z - rv.y * z,
				rv.x * z - x * rv.z,
				x * rv.y - rv.x * y
				);
	}

	public Vect3f inverse() {
		return new Vect3f(-x, -y, -z);
	}
	
	@Override
	public String toString() {
		return "Vect3f [x=" + x + ", y=" + y + ", z=" + z + "]";
	}

	
}